package com.irisblaze.baslib.Particles
{
	import com.irisblaze.baslib.Particles.Enums.EmitterType;
	import com.irisblaze.baslib.Particles.Primitives.IBPCircle;
	import com.irisblaze.baslib.Particles.Enums.ParticleColorType;
	import fl.motion.Color;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.geom.ColorTransform;
	import flash.geom.Vector3D;
	import flash.utils.Timer;
	
	public class Renderer extends MovieClip
	{
		
		private var particleSize:Number;
		private var particlesPerSecond:Number;
		private var particlesGeneratorTimer:Timer;
		private var wind:Vector3D;
		private var gravity:Vector3D;
		private var lastAnimatedTime:Date;
		private var life:Number; // of each particle in seconds
		private var emitterType:Number;
		private var startPosition:Vector3D;
		private var alphaOverLife:Array;
		private var nester:MovieClip;
		private var particleColors:Array;
		private var colorType:Number;
		private var emitterRotation:Vector3D;
		public function Renderer()
		{
			particleSize = 3;
			life = 3; 
			emitterType = EmitterType.Box;
			particlesPerSecond = 100;
			wind = new Vector3D(0, 0, 0);
			gravity = new Vector3D(0, 100, 0);
			startPosition = new Vector3D(0,50, 0);
			alphaOverLife = new Array(1,  0);
			colorType = ParticleColorType.OneColor;
			particleColors = new Array();
			particleColors.push(0xFFFFFF);
			emitterRotation = new Vector3D(0, 0, 360);
			generateParticle();
			if (particlesPerSecond == 0) return;
			particlesGeneratorTimer = new Timer(1000 / particlesPerSecond);
			particlesGeneratorTimer.addEventListener(TimerEvent.TIMER, generateParticle);
			particlesGeneratorTimer.start();
			
			
		}
		
		
		public function setParticleSize(newSize:Number):void
		{
			particleSize = newSize;
		}
		
		public function setParticlesPerSecond(pps:Number):void
		{
			particlesPerSecond = pps;
		}
		
		public function setWind(windv:Vector3D):void
		{
			wind = windv;
		}
		
		public function setGravity(gravityv:Vector3D):void
		{
			gravity = gravityv;
		}
		
		public function setLife(life:Number):void
		{
			this.life = life;
		}
		
		public function setEmitterType(emt:Number):void
		{
			emitterType = emt;
		}
		
		public function setParticlePosition(pos:Vector3D):void
		{
			startPosition = pos;
		}
		
		public function setAlphaOverLife(alphas:Array):void
		{
			alphaOverLife = alphas;
		}
		
		public function setColorType(colorType:Number):void
		{
			this.colorType = colorType;
		}
		
		public function setColors(colors:Array):void
		{
			this.particleColors = colors;
		}
		
		public function setVelocity(v:Vector3D):void
		{
			emitterRotation = v;
		}
		private function generateParticle(ev:TimerEvent=null):void
		{
			nester = new MovieClip();
			var particle:Particle = new Particle();
			if (emitterType == EmitterType.Point)
			{
				particle.x = startPosition.x;
				particle.y = startPosition.y;
				particle.z = startPosition.z;
			}else if (emitterType == EmitterType.Box)
			{
				particle.x = Math.floor(Math.random() * startPosition.x);
				particle.y = Math.floor(Math.random() * startPosition.y);
				particle.z = Math.floor(Math.random() * startPosition.z);
			}
			var ratio:Number = particle.width / particle.height;
			particle.width = particleSize*ratio;
			particle.height = particleSize;
			particle.alpha = alphaOverLife[0];
			
			
			nester.addChild(particle);
			nester.rotationZ = Math.random() * emitterRotation.z;
			nester.rotationX = Math.random() * emitterRotation.x;
			nester.rotationY = Math.random() * emitterRotation.y;
			var ct:ColorTransform = new ColorTransform();
			if (colorType == ParticleColorType.OneColor)
			{
				
				ct.color = particleColors[0];
				particle.transform.colorTransform = ct;
			}else if (colorType == ParticleColorType.RandomColor)
			{
				ct.color = particleColors[Math.floor(Math.random() * particleColors.length)];
				particle.transform.colorTransform = ct;
			}else if (colorType == ParticleColorType.ColorOverLife)
			{
				
				ct.color = particleColors[0];
				particle.transform.colorTransform = ct;
			}
			addChild(nester);
			particle.addEventListener(Event.ENTER_FRAME, moveParticle);
		}
		
		private function moveParticle(ev:Event):void
		{
			var particle:Particle = Particle(ev.target);
			
			
			var now:Date = new Date();
			//let's check if the particle should die first
			if (now.getTime() - particle.birthday.getTime() >= life * 1000)
			{
				particle.removeEventListener(Event.ENTER_FRAME, moveParticle);
				removeChild(particle.parent);
				
				return;
			}
			
			var timeDifference:Number = now.getTime() - particle.lastAnimatedTime.getTime();
			// animate particle according to past time since last animation, since all effectors properties are per second
			// e.g air x effect = 1 per second, thus a particle should move on the x axis 1 unit per 1000 ms 
			var animationRatio:Number = timeDifference / 1000;
			var age:Number = now.getTime() - particle.birthday.getTime();
			var ageRatioToLife:Number = age / (life * 1000);
			
			particle.lastAnimatedTime = new Date();
			particle.x += wind.x*animationRatio;
			particle.y += wind.y*animationRatio;
			particle.z += wind.z*animationRatio;
			particle.x += gravity.x * animationRatio;
			particle.y += gravity.y * animationRatio;
			particle.z += gravity.z * animationRatio;
			
			
			
			if (colorType == ParticleColorType.ColorOverLife)
			{
				var cPeriods:Number = particleColors.length - 1;
				var cperiodLength: Number = life / cPeriods;
				var ccperiod:Number = Math.floor(age / (cperiodLength * 1000));
				var targetColor:Number = particleColors[ccperiod + 1];
				var previousColor:Number = particleColors[ccperiod];
				var ageInColorPeriod:Number = age - (ccperiod * cperiodLength * 1000);
				var ageRatioInCPeriod:Number = ageInColorPeriod / (cperiodLength * 1000);
				
				var currentColor:Number = Color.interpolateColor(previousColor, targetColor, ageRatioInCPeriod);
				var ct:ColorTransform = new ColorTransform();
				ct.color = currentColor;
				particle.transform.colorTransform = ct;
			}
			//alpha over life
			if (alphaOverLife.length==1)
			{
				particle.alpha = alphaOverLife[0];
			}else {
				var periods:Number = alphaOverLife.length - 1;
				var periodLength:Number = life / periods;
				var currentPeriod:Number = Math.floor(age/(periodLength*1000));
				var targetAlpha:Number = alphaOverLife[currentPeriod+1];
				var previousAlpha:Number = alphaOverLife[currentPeriod];
				var ageInPeriod:Number = age  - (currentPeriod * periodLength * 1000);
				
				var ageRatioInPeriod = ageInPeriod/(periodLength*1000)
				
				var alphaDifference:Number = targetAlpha - previousAlpha;
				
				var currentAlpha:Number = previousAlpha + (alphaDifference * ageRatioInPeriod);
				
				particle.alpha = currentAlpha;
			}
			
			
		}
		
	}
}